package com.platform.system.service.impl;

import com.alibaba.dashscope.utils.JsonUtils;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.platform.common.constant.Constants;
import com.platform.common.constant.HttpStatus;
import com.platform.common.core.domain.AjaxResult;
import com.platform.common.core.page.TableDataInfo;
import com.platform.common.enums.ResultEnum;
import com.platform.common.exception.BusinessException;
import com.platform.common.utils.StringUtils;
import com.platform.common.utils.bean.BeanUtils;
import com.platform.common.utils.uuid.SnowflakeIdWorker;
import com.platform.quartz.domain.SysJob;
import com.platform.quartz.service.ISysJobService;
import com.platform.quartz.util.CronUtils;
import com.platform.system.domain.dto.device.DeviceInfoDto;
import com.platform.system.domain.dto.device.FirmwareInfoDto;
import com.platform.system.domain.dto.device.UpgradeTaskDto;
import com.platform.system.domain.entity.device.FirmwareInfo;
import com.platform.system.domain.entity.device.UpgradeTask;
import com.platform.system.domain.vo.device.UpgradeTaskVo;
import com.platform.system.enums.TopicEnums;
import com.platform.system.mapper.device.UpgradeTaskMapper;
import com.platform.system.mqtt.utils.MqttService;
import com.platform.system.service.ISysDeviceInfoService;
import com.platform.system.service.ISysFileService;
import com.platform.system.service.ISysFirmwareInfoService;
import com.platform.system.service.ISysUpgradeTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Huangkai
 */
@Service
@Slf4j
public class SysUpgradeTaskServiceImpl extends ServiceImpl<UpgradeTaskMapper, UpgradeTask> implements ISysUpgradeTaskService {

    @Resource
    UpgradeTaskMapper upgradeTaskMapper;

    @Resource
    ISysFirmwareInfoService sysFirmwareInfoService;

    @Resource
    ISysDeviceInfoService sysDeviceInfoService;

    @Resource
    MqttService mqttService;

    @Resource
    ISysJobService sysJobService;

    @Override
    public TableDataInfo selectUpgradeTaskList(UpgradeTaskVo upgradeTaskVo) {
        if(StringUtils.isNotEmpty(upgradeTaskVo.getVersion())){
            upgradeTaskVo.setFirmwareUid("-1");
            FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfoByVersion(upgradeTaskVo.getVersion(), Constants.NUM_ZERO);
            log.info("查询包{}", firmwareInfoDto);
            if(firmwareInfoDto != null){
                upgradeTaskVo.setFirmwareUid(firmwareInfoDto.getUid());
            }
        }
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.like(upgradeTaskVo.getName() != null, UpgradeTask::getName, upgradeTaskVo.getName());
        taskLambdaQueryWrapper.eq(upgradeTaskVo.getFirmwareUid() != null, UpgradeTask::getFirmwareUid, upgradeTaskVo.getFirmwareUid());
        taskLambdaQueryWrapper.eq(upgradeTaskVo.getType() != null, UpgradeTask::getType, upgradeTaskVo.getType());
        taskLambdaQueryWrapper.eq(upgradeTaskVo.getStatus() != null, UpgradeTask::getStatus, upgradeTaskVo.getStatus());
        taskLambdaQueryWrapper.orderByDesc(UpgradeTask::getCreateTime);
        Page<UpgradeTask> page = new Page<>();
        page.setCurrent(upgradeTaskVo.getPageNum());
        page.setSize(upgradeTaskVo.getPageSize());
        IPage<UpgradeTask> fileIPage = upgradeTaskMapper.selectPage(page, taskLambdaQueryWrapper);
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        List<UpgradeTaskDto> upgradeTaskDtoList = new ArrayList<>();
        if(fileIPage.getRecords() != null && fileIPage.getRecords().size() > 0){
            String json = JSONArray.toJSONString(fileIPage.getRecords());
            upgradeTaskDtoList = JSONArray.parseArray(json, UpgradeTaskDto.class);
            List<String> upgradeUidList = upgradeTaskDtoList.stream().map(UpgradeTaskDto::getFirmwareUid).collect(Collectors.toList());
            List<FirmwareInfoDto> firmwareInfoDtoList = sysFirmwareInfoService.selectFirmwareInfoByUidList(upgradeUidList);
            Map<String, List<FirmwareInfoDto>> firmwareInfoDtoMap = firmwareInfoDtoList.stream().collect(Collectors.groupingBy(FirmwareInfoDto::getUid));
            upgradeTaskDtoList.forEach(upgradeTaskDto -> {
                if(firmwareInfoDtoMap != null && firmwareInfoDtoMap.containsKey(upgradeTaskDto.getFirmwareUid())){
                    FirmwareInfoDto firmwareInfoDto = firmwareInfoDtoMap.get(upgradeTaskDto.getFirmwareUid()).get(0);
                    upgradeTaskDto.setFirmwareInfoDto(firmwareInfoDto);
                }
            });
        }
        rspData.setRows(upgradeTaskDtoList);
        rspData.setTotal(fileIPage.getTotal());
        return rspData;
    }

    @Override
    public UpgradeTaskDto selectUpgradeTaskMostNew(UpgradeTaskVo upgradeTaskVo) {
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getType, upgradeTaskVo.getType());
        taskLambdaQueryWrapper.orderByAsc(UpgradeTask::getCreateTime);
        taskLambdaQueryWrapper.last("limit 1");
        UpgradeTask upgradeTask = upgradeTaskMapper.selectOne(taskLambdaQueryWrapper);
        if(upgradeTask != null) {
            UpgradeTaskDto upgradeTaskDto = new UpgradeTaskDto();
            BeanUtils.copyProperties(upgradeTask, upgradeTaskDto);
            FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfo(upgradeTask.getFirmwareUid());
            if(firmwareInfoDto != null){
                upgradeTaskDto.setFirmwareInfoDto(firmwareInfoDto);
            }
            return upgradeTaskDto;
        }
        return null;
    }

    @Override
    public UpgradeTaskDto selectUpgradeTask(String uid) {
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getUid, uid);
        UpgradeTask upgradeTask = upgradeTaskMapper.selectOne(taskLambdaQueryWrapper);
        if(upgradeTask != null) {
            UpgradeTaskDto upgradeTaskDto = new UpgradeTaskDto();
            BeanUtils.copyProperties(upgradeTask, upgradeTaskDto);
            FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfo(upgradeTask.getFirmwareUid());
            log.info("安装包信息{}", JsonUtils.toJson(firmwareInfoDto));
            if(firmwareInfoDto != null){
                upgradeTaskDto.setFirmwareInfoDto(firmwareInfoDto);
            }
            return upgradeTaskDto;
        }
        return null;
    }

    @Override
    public AjaxResult insertUpgradeTask(UpgradeTaskVo upgradeTaskVo) {
        FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfo(upgradeTaskVo.getFirmwareUid());
        if(firmwareInfoDto == null){
            throw new BusinessException(ResultEnum.UPGRADE_FILE);
        }
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getFirmwareUid, upgradeTaskVo.getFirmwareUid());
        UpgradeTask upgradeTask = upgradeTaskMapper.selectOne(taskLambdaQueryWrapper);
        if(upgradeTask != null){
            ResultEnum resultEnum = ResultEnum.UPGRADE_TASK;
            resultEnum.setMessage(String.format(resultEnum.getMessage(), firmwareInfoDto.getVersion()));
            throw new BusinessException(resultEnum);
        }
        if (!CronUtils.isValid(upgradeTaskVo.getTaskCron())) {
            throw new BusinessException(ResultEnum.CRON_ERROR);
        }
        upgradeTask = new UpgradeTask();
        upgradeTask.setUid(SnowflakeIdWorker.getSnowflakeIdWorker());
        upgradeTask.setName(upgradeTaskVo.getName());
        upgradeTask.setTaskCron(upgradeTaskVo.getTaskCron());
        upgradeTask.setIsAll(upgradeTaskVo.getIsAll());
        upgradeTask.setRegexpSymbol(upgradeTaskVo.getRegexpSymbol());
        upgradeTask.setFirmwareUid(upgradeTaskVo.getFirmwareUid());
        upgradeTask.setParam(upgradeTaskVo.getParam());
        upgradeTask.setStatus(Constants.NUM_ZERO);
        upgradeTask.setType(upgradeTaskVo.getType());
        upgradeTask.setSort(Constants.NUM_ZERO);
        upgradeTask.setIsDel(Constants.NUM_ZERO);
        upgradeTask.setCreateTime(new Date());
        upgradeTask.setUpdateTime(new Date());
        upgradeTask.setRemark(upgradeTaskVo.getRemark());
        upgradeTask.insert();

        /*
        SysJob sysJob = new SysJob();
        sysJob.setJobGroup("DEVICE_UPGRADE");
        //立即执行
        sysJob.setMisfirePolicy(Constants.STR_ONE);
        sysJob.setCronExpression(upgradeTaskVo.getTaskCron());
        sysJob.setConcurrent(Constants.STR_ZERO);
        sysJobService.insertJob(sysJob)

         */

        return AjaxResult.success();
    }

    @Override
    public AjaxResult updateUpgradeTaskStatus(UpgradeTaskVo upgradeTaskVo) {
        UpgradeTaskDto upgradeTaskDto = selectUpgradeTask(upgradeTaskVo.getUid());
        if(upgradeTaskDto == null){
            throw new BusinessException(ResultEnum.DATA_NOT_EXIST);
        }
        log.info("修改的信息{}", upgradeTaskVo);
        FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfo(upgradeTaskDto.getFirmwareUid());
        if(firmwareInfoDto == null){
            throw new BusinessException(ResultEnum.UPGRADE_FILE);
        }
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getUid, upgradeTaskVo.getUid());
        UpgradeTask upgradeTask = new UpgradeTask();
        upgradeTask.setStatus(Constants.NUM_ONE);
        upgradeTask.setStartTime(new Date());
        upgradeTask.update(taskLambdaQueryWrapper);

        List<DeviceInfoDto> deviceInfoDtoList;
        if(upgradeTask.getIsAll().equals(Constants.NUM_ZERO)){
            deviceInfoDtoList = sysDeviceInfoService.selectDeviceInfoByRegexp(upgradeTaskDto.getRegexpSymbol());
        }else{
            deviceInfoDtoList = sysDeviceInfoService.selectDeviceInfoByRegexp(null);
        }
        if(CollectionUtils.isEmpty(deviceInfoDtoList)){
            throw new BusinessException(ResultEnum.UPGRADE_DEVICE_NOT_EXIST);
        }
        //发送mqtt
        List<String> clientIdList = deviceInfoDtoList.stream().map(DeviceInfoDto::getAuthKey).collect(Collectors.toList());
        mqttService.publishToClient(clientIdList, TopicEnums.DEVICE_UPGRADE.getTopic(), JSONObject.toJSONString(upgradeTaskDto));
        return AjaxResult.success();

    }

    @Override
    public AjaxResult updateUpgradeTask(UpgradeTaskVo upgradeTaskVo) {
        UpgradeTaskDto upgradeTaskDto = selectUpgradeTask(upgradeTaskVo.getUid());
        if(upgradeTaskDto == null){
            throw new BusinessException(ResultEnum.DATA_NOT_EXIST);
        }
        log.info("修改的信息{}", upgradeTaskVo);
        FirmwareInfoDto firmwareInfoDto = sysFirmwareInfoService.selectFirmwareInfo(upgradeTaskDto.getFirmwareUid());
        if(firmwareInfoDto == null){
            throw new BusinessException(ResultEnum.UPGRADE_FILE);
        }
        List<Integer> statusList = Lists.newArrayList(Constants.NUM_ZERO, Constants.NUM_THREE);
        if(!statusList.contains(upgradeTaskDto.getStatus())){
            throw new BusinessException(ResultEnum.UPGRADE_FINISH_PROGRESS);
        }
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getUid, upgradeTaskVo.getUid());
        UpgradeTask upgradeTask = new UpgradeTask();
        BeanUtils.copyProperties(upgradeTaskVo, upgradeTask);
        upgradeTask.setUpdateTime(new Date());
        if(upgradeTaskVo.getType().equals(Constants.NUM_ZERO)){
            upgradeTask.setTaskCron("");
        }
        upgradeTask.update(taskLambdaQueryWrapper);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult deleteUpgradeTask(UpgradeTaskVo upgradeTaskVo) {
        UpgradeTaskDto upgradeTaskDto = selectUpgradeTask(upgradeTaskVo.getUid());
        if(upgradeTaskDto == null){
            throw new BusinessException(ResultEnum.DATA_NOT_EXIST);
        }
        if(upgradeTaskDto.getStatus() == Constants.NUM_ONE){
            throw new BusinessException(ResultEnum.UPGRADE_PROGRESS);
        }
        LambdaQueryWrapper<UpgradeTask> taskLambdaQueryWrapper = new QueryWrapper<UpgradeTask>().lambda();
        taskLambdaQueryWrapper.eq(UpgradeTask::getUid, upgradeTaskVo.getUid());
        upgradeTaskMapper.delete(taskLambdaQueryWrapper);
        return AjaxResult.success();
    }
}
